﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Zero.UControl.Component
{
    /// <summary>
    /// FloatingBlock.xaml 的交互逻辑
    /// </summary>
    public partial class FloatingBlock : UserControl
    {
        public FloatingBlock()
        {
            InitializeComponent();
        }


        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(FloatingBlock), new PropertyMetadata("👍", OnTextChanged));

        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            string oldVal = e.OldValue.ToString();
            string newVal = e.NewValue.ToString();
            if(oldVal != newVal)
            {
                (d as FloatingBlock).FloatingButton.Content = newVal;
            }
        }

        private double floatingDuration = 1;

        public double FloatingDuration
        {
            get { return floatingDuration; }
            set { floatingDuration = value; }
        }

        private double floatingDistance = 150;

        public double FloatingDistance
        {
            get { return floatingDistance; }
            set { floatingDistance = value; }
        }


        private void FloatingButton_Click(object sender, RoutedEventArgs e)
        {
            var button = (Button)sender;

            // 第一步：将当前的局部坐标系转换为相对于Window的窗口坐标系
            // 第二步：获取按钮局部坐标系的左上角位置相对于Window窗口左上角的位置
            Point position = button.TransformToAncestor(this).Transform(new Point(0, 0));
            // 获取鼠标相对于当前窗口的位置
            //Point position = Mouse.GetPosition(this);

            var floatingText = new TextBlock
            {
                Text = button.Content.ToString(),
                FontSize = 24,
                FontFamily = button.FontFamily,
                Foreground = button.Foreground
            };

            FloatingCanvas.Children.Add(floatingText);
            floatingText.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

            // 此时可以获取 DesiredSize
            double width = floatingText.DesiredSize.Width;
            double height = floatingText.DesiredSize.Height;

            position.X = position.X + button.ActualWidth / 2 - width / 2;
            position.Y = position.Y + button.ActualHeight / 2 - height / 2;
            // 设置初始位置
            Canvas.SetLeft(floatingText, position.X);
            Canvas.SetTop(floatingText, position.Y);

            // Double的关键帧,这里不能使用路径关键帧，因为通过 Tranlate.X 或 Translate.Y 无法移动超出父容器范围
            var xAnimation = new DoubleAnimationUsingKeyFrames
            {
                Duration = TimeSpan.FromSeconds(FloatingDuration)
            };
            xAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(position.X, KeyTime.FromTimeSpan(TimeSpan.Zero)));
            xAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(position.X, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(FloatingDuration / 2))));
            xAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(position.X + FloatingDistance / 3, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(FloatingDuration))));

            var yAnimation = new DoubleAnimationUsingKeyFrames
            {
                Duration = TimeSpan.FromSeconds(FloatingDuration)
            };
            yAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(position.Y, KeyTime.FromTimeSpan(TimeSpan.Zero))); 
            yAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(position.Y - FloatingDistance / 2, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(FloatingDuration / 2))));
            yAnimation.KeyFrames.Add(new LinearDoubleKeyFrame(position.Y - FloatingDistance, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(FloatingDuration))));


            var fadeOutAnimation = new DoubleAnimation
            {
                From = 1.0,
                To = 0.0,
                Duration = TimeSpan.FromSeconds(FloatingDuration)
            };


            floatingText.BeginAnimation(TextBlock.OpacityProperty, fadeOutAnimation);

            // 绑定路径动画到 Canvas.Left 和 Canvas.Top
            // 注意：
            //      这里不能通过Translate.X 于 Transalate.Y 来进行移动，通过这种方式控制移动的话浮动效果不会超出Canvas
            Storyboard.SetTarget(xAnimation, floatingText);
            Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(Canvas.Left)"));

            Storyboard.SetTarget(yAnimation, floatingText);
            Storyboard.SetTargetProperty(yAnimation, new PropertyPath("(Canvas.Top)"));


            var storyboard = new Storyboard();
            storyboard.Children.Add(xAnimation);
            storyboard.Children.Add(yAnimation);

            storyboard.Completed += (s, a) => FloatingCanvas.Children.Remove(floatingText);
            storyboard.Begin();
        }
    }
}
